package com.qipay.api.alipay.controller.v1;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.qipay.api.alipay.controller.v1.vo.CpPayAlipayNativeVo;
import com.qipay.api.alipay.controller.v1.vo.CpPayAlipayWapVo;
import com.qipay.api.wx.controller.v1.vo.CpPayWeiXinNativeVo;
import com.qipay.baas.model.Cp;
import com.qipay.baas.model.CpChannel;
import com.qipay.baas.model.Order;
import com.qipay.core.help.DicHelper;
import com.qipay.cp.CpService;
import com.qipay.cpchannel.service.CpChannelService;
import com.qipay.order.config.OrderSettleStateEnum;
import com.qipay.order.config.OrderStateEnum;
import com.qipay.order.service.OrderService;
import com.qipay.pay.AlipayService;
import com.qipay.pay.AlipayWapService;
import com.qipay.pay.WeiXinPayService;
import com.qipay.pay.entity.CpPayAlipayNativeRequest;
import com.qipay.pay.entity.CpPayAlipayWapRequest;
import com.qipay.pay.entity.CpPayWeiXinNativeRequest;
import com.qipay.scalar.type.ApiStatusEnum;
import com.qipay.scalar.type.ChannelTypeEnum;
import com.qipay.security.jwt.JWTUser;
import com.qipay.security.sign.service.SignService;
import com.qipay.sp.SpApiConfigService;
import com.qipay.sp.SpConfigService;
import com.qipay.sp.SpService;
import com.qipay.sp.excutor.ExcutorFactory;
import com.qipay.utils.ResultUtils;
import com.qipay.utils.XmlUtils;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.*;

@RestController
@RequestMapping("/redirect/v1/alipay")
public class AlipayRedirectController {

    protected final Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    CpService cpService;

    @Autowired
    SignService signService;

    @Autowired
    AlipayWapService alipayWapService;

    @Autowired
    AlipayService alipayService;

    @Autowired
    OrderService orderService;

    @Autowired
    SpConfigService spConfigService;

    @Autowired
    SpApiConfigService spApiConfigService;

    @Autowired
    ObjectMapper objectMapper;

    @Autowired
    SpService spService;

    @Value("${api.response.sign.name}")
    private String sigKey;

    @Autowired
    WeiXinPayService weiXinPayService;
    /**
     * 自定义的重定向
     */
    @RequestMapping(value = "/test", method = RequestMethod.GET, produces = {"application/xml;charset=UTF-8"})
    public String test(
            HttpServletRequest request,
            @RequestParam("spId") Integer spId,
            @RequestParam("type") String type,
            @RequestParam(name = "money",required = false,defaultValue = "") String money,
            HttpServletResponse response
    ) throws Exception {
        String secret = "d8bcecebcf1a42e38516b7dbbbc64a4b";
        Assert.notNull(spId, "请输入spId");
        Assert.notNull(type, "请输入测试接口类型");
        JWTUser user = new JWTUser(1000003L,"1000003","test:1000003:"+spId,new Date(),secret);
        Map<String, Object> params = new HashMap<>();
        params.put("nonce_str","123456789");
        params.put("out_trade_no","test"+orderService.createOrder(18));
        params.put("total_fee","".equals(money)?"15":money);
        params.put("sign","123456789");
        params.put("body","test");
        params.put("mch_id","1000003");
        params.put("notify_url","http://localhost:8080");
        params.put("version","1");
        params.put("mch_create_ip","127.0.0.1");

        Map<String, Object> result = null;
        if(type.equals("alipay_native")){
            CpPayAlipayNativeVo vo = (CpPayAlipayNativeVo) XmlUtils.mapToBean(
                    params, CpPayAlipayNativeVo.class);
            CpPayAlipayNativeRequest bean = new CpPayAlipayNativeRequest();
            BeanUtils.copyProperties(vo, bean);
            result = alipayService.payNative(bean, user);
        }else if(type.equals("alipay_wap")){
            CpPayAlipayWapVo vo = (CpPayAlipayWapVo) XmlUtils.mapToBean(
                    params, CpPayAlipayWapVo.class);
            CpPayAlipayWapRequest bean = new CpPayAlipayWapRequest();
            BeanUtils.copyProperties(vo, bean);
            result = alipayWapService.wapPayCreateOrder(bean,user);
        }else if(type.equals("wx_native")){
            CpPayWeiXinNativeVo vo = (CpPayWeiXinNativeVo) XmlUtils.mapToBean(
                    params, CpPayWeiXinNativeVo.class);
            CpPayWeiXinNativeRequest bean = new CpPayWeiXinNativeRequest();
            BeanUtils.copyProperties(vo, bean);
            result = weiXinPayService.payWeixinNative(bean, user);
        }

        return XmlUtils.toString(result, "xml");
    }

    /**
     * 自定义的重定向
     */
    @RequestMapping(value = "/my", method = RequestMethod.GET, produces = {"application/xml;charset=UTF-8"})
    private ModelAndView my(
            HttpServletRequest request,
            @RequestParam("id") String id,
            HttpServletResponse response
    ) throws Exception {
        Assert.notNull(id, "请输入订单号");
        Order order = orderService.getByTradeNo(id);
        Assert.notNull(order, "订单号错误");
        Assert.isTrue(order.getState()==1,"订单重复或者已支付");

        String result = order.getRemark();
        ModelAndView modelAndView = new ModelAndView("/pay/online_bank");
        modelAndView.addObject("result", result);
        return modelAndView;
    }

    /**
     * 三方的支付宝
     * @param request
     * @param mchId
     * @param tradeNo
     * @param nonceStr
     * @param sign
     * @param response
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/otherwap", method = RequestMethod.GET, produces = {"application/xml;charset=UTF-8"})
    private void otherwap(
            HttpServletRequest request,
            @RequestParam("mch_id") String mchId,
            @RequestParam("trade_no") String tradeNo,
            @RequestParam("nonce_str") String nonceStr,
            @RequestParam("sign") String sign,
            HttpServletResponse response
    ) throws Exception {
        Assert.notNull(mchId, "请输入商户ID");
        Assert.notNull(tradeNo, "请输入平台交易流水");
        Assert.notNull(nonceStr, "请输入随机字符串");
        Assert.notNull(sign, "请输入签名");

        Cp cp = cpService.getOneByAppId(mchId);
        Assert.notNull(cp,"错误的商户ID");

        Map<String, Object> params = new HashMap<>();
        params.put("mch_id",mchId);
        params.put("trade_no",tradeNo);
        params.put("nonce_str",nonceStr);
        params.put("sign",sign);
        String fromSig = params.get(sigKey).toString();
        String mySig = signService.getSign(params, cp.getSecretId(), sigKey);
        Assert.isTrue(StringUtils.equals(fromSig, mySig),"签名错误");

        Order order = orderService.getByTradeNo(tradeNo);
        Assert.notNull(order, "错误的订单信息");
        Assert.isTrue(mchId.equals(order.getCpId().toString()),"输入的商户号与订单信息不一致");
        Assert.isTrue(Objects.equals(order.getState(), OrderStateEnum.NOTPAY.getType()),
                ResultUtils.buildErrorMsg(ApiStatusEnum.ARGUMENT_ERR,"错误的订单信息"));

        Map<String, Object> payInfoMap =  alipayWapService.wapPay(order.getId());

        Assert.notNull(payInfoMap,
                ResultUtils.buildErrorMsg(ApiStatusEnum.SERVICE_ERR,"请求sp的支付宝wap支付失败"));
        Assert.isTrue(payInfoMap.containsKey("result_code"),
                ResultUtils.buildErrorMsg(ApiStatusEnum.SERVICE_ERR,"请求sp的支付宝wap支付失败"));
        Assert.isTrue("0".equals(payInfoMap.get("result_code").toString()),
                ResultUtils.buildErrorMsg(ApiStatusEnum.SERVICE_ERR,"请求sp的支付宝wap支付失败"));
        Assert.notNull(payInfoMap.get("redirect_url"),
                ResultUtils.buildErrorMsg(ApiStatusEnum.SERVICE_ERR,"请求sp的支付宝wap支付失败"));

        String redirect_url = payInfoMap.get("redirect_url").toString();
        response.sendRedirect(redirect_url);
    }

    /**
     * 原生的支付宝
     * @param request
     * @param mchId
     * @param tradeNo
     * @param nonceStr
     * @param sign
     * @param response
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/wap", method = RequestMethod.GET, produces = {"application/xml;charset=UTF-8"})
    private ModelAndView wap(
            HttpServletRequest request,
            @RequestParam("mch_id") String mchId,
            @RequestParam("trade_no") String tradeNo,
            @RequestParam("nonce_str") String nonceStr,
            @RequestParam("type") String type,
            @RequestParam("sign") String sign,
            HttpServletResponse response
    ) throws Exception {
        Assert.notNull(mchId, "请输入商户ID");
        Assert.notNull(tradeNo, "请输入平台交易流水");
        Assert.notNull(nonceStr, "请输入随机字符串");
        Assert.notNull(sign, "请输入签名");

        Cp cp = cpService.getOneByAppId(mchId);
        Assert.notNull(cp,"错误的商户ID");

        Map<String, Object> params = new HashMap<>();
        params.put("mch_id",mchId);
        params.put("trade_no",tradeNo);
        params.put("nonce_str",nonceStr);
        params.put("type",type);
        params.put("sign",sign);
        String fromSig = params.get(sigKey).toString();
        String mySig = signService.getSign(params, cp.getSecretId(), sigKey);
        Assert.isTrue(StringUtils.equals(fromSig, mySig),"签名错误");

        Order order = orderService.getByTradeNo(tradeNo);
        Assert.notNull(order, "错误的订单信息");
        Assert.isTrue(mchId.equals(order.getCpId().toString()),"输入的商户号与订单信息不一致");
        Assert.isTrue(Objects.equals(order.getState(), OrderStateEnum.NOTPAY.getType()),
                ResultUtils.buildErrorMsg(ApiStatusEnum.ARGUMENT_ERR,"错误的订单信息"));

        Map<String, Object> payInfoMap = null;
        if("native".equals(type)){
            payInfoMap =  alipayService.nativePay(order.getId());
        }else{
            payInfoMap =  alipayWapService.wapPay(order.getId());
        }

        Assert.notNull(payInfoMap,
                ResultUtils.buildErrorMsg(ApiStatusEnum.SERVICE_ERR,"请求sp的支付宝wap支付失败"));
        Assert.isTrue(payInfoMap.containsKey("result_code"),
                ResultUtils.buildErrorMsg(ApiStatusEnum.SERVICE_ERR,"请求sp的支付宝wap支付失败"));
        Assert.isTrue("0".equals(payInfoMap.get("result_code").toString()),
                ResultUtils.buildErrorMsg(ApiStatusEnum.SERVICE_ERR,"请求sp的支付宝wap支付失败"));
        Assert.notNull(payInfoMap.get("pay_info"),
                ResultUtils.buildErrorMsg(ApiStatusEnum.SERVICE_ERR,"请求sp的支付宝wap支付失败"));

        String payInfo = payInfoMap.get("pay_info").toString();
        ModelAndView modelAndView = new ModelAndView("/pay/wap_script");
        modelAndView.addObject("pay_info", payInfo);
        return modelAndView;
    }

    @RequestMapping(value = "/ykAlipayWap", method = RequestMethod.GET, produces = {"application/xml;charset=UTF-8"})
    private ModelAndView ykAlipayWap(
            HttpServletRequest request,
            @RequestParam("mch_id") String mchId,
            @RequestParam("trade_no") String tradeNo,
            @RequestParam("nonce_str") String nonceStr,
            @RequestParam("sign") String sign,
            HttpServletResponse response
    ) throws Exception {
        Assert.notNull(mchId, "请输入商户ID");
        Assert.notNull(tradeNo, "请输入平台交易流水");
        Assert.notNull(nonceStr, "请输入随机字符串");
        Assert.notNull(sign, "请输入签名");

        Cp cp = cpService.getOneByAppId(mchId);
        Assert.notNull(cp,"错误的商户ID");

        Map<String, Object> params = new HashMap<>();
        params.put("mch_id",mchId);
        params.put("trade_no",tradeNo);
        params.put("nonce_str",nonceStr);
        params.put("sign",sign);
        String fromSig = params.get(sigKey).toString();
        String mySig = signService.getSign(params, cp.getSecretId(), sigKey);
        Assert.isTrue(StringUtils.equals(fromSig, mySig),"签名错误");

        Order order = orderService.getByTradeNo(tradeNo);
        Assert.notNull(order, "错误的订单信息");
        Assert.isTrue(mchId.equals(order.getCpId().toString()),"输入的商户号与订单信息不一致");
        Assert.isTrue(Objects.equals(order.getState(), OrderStateEnum.NOTPAY.getType()),
                ResultUtils.buildErrorMsg(ApiStatusEnum.ARGUMENT_ERR,"错误的订单信息"));

        Map<String, Object> payInfoMap =  alipayWapService.wapPay(order.getId());

        Assert.notNull(payInfoMap,
                ResultUtils.buildErrorMsg(ApiStatusEnum.SERVICE_ERR,"请求赢酷的支付宝wap支付失败"));
        Assert.isTrue(payInfoMap.containsKey("result_code"),
                ResultUtils.buildErrorMsg(ApiStatusEnum.SERVICE_ERR,"请求赢酷的支付宝wap支付失败"));
        Assert.isTrue("0".equals(payInfoMap.get("result_code").toString()),
                ResultUtils.buildErrorMsg(ApiStatusEnum.SERVICE_ERR,"请求赢酷的支付宝wap支付失败"));
        Assert.notNull(payInfoMap.get("htmlresult"),
                ResultUtils.buildErrorMsg(ApiStatusEnum.SERVICE_ERR,"请求赢酷的支付宝wap支付失败"));

        String htmlresult = payInfoMap.get("htmlresult").toString();
        ModelAndView modelAndView = new ModelAndView("/pay/online_bank");
        modelAndView.addObject("result", htmlresult);
        return modelAndView;
    }

}
